home *** CD-ROM | disk | FTP | other *** search
- ;-----------------------------------------------------------------------;
- ; CLOCK.ASM ;
- ; ;
- ; Pictor, Version 1.51, Copyright (c) 1992-94 SoftCircuits. ;
- ; Redistributed by permission. ;
- ;-----------------------------------------------------------------------;
- % .MODEL memmodel,c
-
- EXTRN atexit:PROC
-
- .DATA
- EXTRN _PL_segment:WORD,_PL_columns:WORD
- EXTRN _PL_snowcheck:WORD
-
- show_row DW 0 ;Screen coordinates for clock
- show_column DW 0
-
- time_buffer DB "0 0 : 0 0 a m "
- TIME_BUFFER_LEN EQU (($-time_buffer)/2)
-
- installed_flag DB 0 ;1 = handler is installed
- registered_flag DB 0 ;1 = removeclock registered w/atexit
- counter DW 0 ;
-
-
- .CODE
- old1C_handler DD 0 ;Save old handler in code segment
-
- ;-----------------------------------------------------------------------;
- ; Creates an ASCII time string based on the current time. ;
- ; ;
- ; Usage: This procedure cannot be called directly from C. ;
- ;-----------------------------------------------------------------------;
- IFDEF ??version ;Turbo Assembler
- create_time PROC NEAR
- ELSE
- create_time PROC NEAR PRIVATE
- ENDIF
- mov time_buffer[10],'a' ;Assume 'am' for now
- mov ax,0040h
- mov es,ax
- mov ax,es:[006Eh] ;Read timer high count
- mov bx,ax ;Preserve ax
- mov ax,12 ;Assume midnight
- cmp bx,0 ;Is it midnight?
- je set_hours ;Yes
- mov ax,bx ;Else restore ax
- cmp ax,12 ;Is it before noon?
- jb set_hours ;Yes, 'am' okay
- mov time_buffer[10],'p' ;Else must be 'pm'
- cmp al,12 ;Noon?
- je set_hours ;Yes
- sub al,12 ;Else adjust 'pm' hours
- set_hours:
- aam ;Convert al to binary coded decimal
- add ax,3030h ;Convert ax to 2 ASCII digits
- cmp ah,'0' ;Is leading digit '0'?
- jne hours_ok ;No, hours are ok
- mov ah,' ' ;Else clear leading '0'
- hours_ok:
- mov time_buffer[0],ah ;Create hour portion of string
- mov time_buffer[2],al
- mov al,es:[006Dh] ;Read timer low count
- mov dl,60
- mul dl
- mov al,ah
- aam ;Convert al to binary coded decimal
- add ax,3030h ;Convert ax to 2 ASCII digits
- mov time_buffer[6],ah ;Create minutes portion of string
- mov time_buffer[8],al
- ret
- create_time ENDP
-
- ;-----------------------------------------------------------------------;
- ; Displays the time string to the screen. ;
- ; ;
- ; Usage: This procedure cannot be called directly from C. ;
- ;-----------------------------------------------------------------------;
- IFDEF ??version ;Turbo Assembler
- show_time PROC NEAR
- ELSE
- show_time PROC NEAR PRIVATE
- ENDIF
- cld
- mov si,OFFSET time_buffer ;ds:si = string, es:di = screen
- mov es,_PL_segment
- mov ax,show_row
- mul BYTE PTR _PL_columns
- add ax,show_column
- shl ax,1
- mov di,ax
- mov cx,TIME_BUFFER_LEN
- cmp _PL_snowcheck,0
- je no_snow_check
- mov dx,03DAh ;CGA status port address
- snow_check:
- lodsw
- mov bx,ax
- scan_low:
- in al,dx
- shr al,1
- jc scan_low
- cli
- scan_high:
- in al,dx
- shr al,1
- jnc scan_high
- xchg ax,bx
- stosw
- sti
- loop snow_check
- ret
- no_snow_check:
- rep movsw
- ret
- show_time ENDP
-
- ;-----------------------------------------------------------------------;
- ; Timer interrupt handler. If the counter has expired, the time string ;
- ; is updated to reflect the current time. In either case, the time ;
- ; string is written to the screen and this procedure chains to the ;
- ; original timer handler. ;
- ; ;
- ; Usage: This procedure cannot be called directly from C. ;
- ;-----------------------------------------------------------------------;
- IFDEF ??version ;Turbo Assembler
- int1C_handler PROC FAR
- ELSE
- int1C_handler PROC FAR PRIVATE
- ENDIF
- sti ;Interrupts on
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- push bp
- push ds
- push es
- mov ax,@Data ;ds = data segment
- mov ds,ax
- dec counter ;Decrement counter
- jns display_time ;Display only if no underflow
- call create_time ;Else update time string
- mov counter,500 ;Reset timer
- display_time:
- call show_time ;Display time
- pop es
- pop ds
- pop bp
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- cli ;Handler expects interrupts off
- jmp cs:old1C_handler ;Chain to original handler
- int1C_handler ENDP
-
- PUBLIC removeclock
- ;-----------------------------------------------------------------------;
- ; Deactivates the clock by removing the clock interrupt handler. This ;
- ; function fails if the handler has not been installed, or if the ;
- ; interrupt vector has been modified since the handler was installed. ;
- ; ;
- ; Usage: int removeclock(void); ;
- ; Returns: 0 = success, -1 = error ;
- ;-----------------------------------------------------------------------;
- removeclock PROC
- mov ax,-1 ;Return error if we haven't
- cmp installed_flag,0 ; installed our handler
- je end_removeclock
- mov ax,351Ch ;Get interrupt 1Ch vector
- int 21h
- mov ax,-1 ;Return error if vector doesn't
- cmp bx,OFFSET int1C_handler ; still point to our handler
- jne end_removeclock
- mov bx,es
- mov ax,cs
- cmp ax,bx
- jne end_removeclock
- mov ax,251Ch ;Restore original vector
- push ds
- lds dx,cs:old1C_handler
- int 21h
- pop ds ;Restore ds
- mov installed_flag,0 ;Indicate we're no longer installed
- sub ax,ax
- end_removeclock:
- ret
- removeclock ENDP
-
- PUBLIC installclock
- ;-----------------------------------------------------------------------;
- ; Installs an interrupt handler that will display the time at the ;
- ; specified location. It then registers removeclock with the ANSI C ;
- ; library function atexit(). ;
- ; ;
- ; Usage: int installclock(int row,int column,int color); ;
- ; Returns: 0 = success, -1 = error ;
- ;-----------------------------------------------------------------------;
- installclock PROC USES si, row:WORD,column:WORD,color:WORD
- mov ax,-1 ;Return error if were already
- cmp installed_flag,1 ; installed
- je end_installclock
- mov ax,row ;Adjust and save screen coordinates
- dec ax
- mov show_row,ax
- mov ax,column
- dec ax
- mov show_column,ax
- mov ax,color ;Set attribute bytes of buffer to
- mov si,OFFSET time_buffer+1 ; specified color
- mov cx,TIME_BUFFER_LEN
- color_loop:
- mov [si],al
- add si,2
- loop color_loop
- mov ax,351Ch ;Get old timer interrupt vector
- int 21h
- mov WORD PTR cs:old1C_handler[0],bx
- mov WORD PTR cs:old1C_handler[2],es
- push ds ;Set new timer interrupt vector
- mov ax,251Ch
- push cs
- pop ds
- mov dx,OFFSET int1C_handler
- int 21h
- pop ds
- mov installed_flag,1 ;Indicate we've been installed
- mov ax,0
- cmp registered_flag,1
- je end_installclock
- mov registered_flag,1
- IF @CodeSize ;Register removeclock with atexit()
- push cs
- ENDIF
- mov ax,OFFSET removeclock
- push ax
- call atexit
- IF @CodeSize
- add sp,4
- ELSE
- inc sp
- inc sp
- ENDIF
- cmp ax,0 ;Was atexit() successful?
- je end_installclock ;Yes, return 0
- call removeclock ;Else uninstall handler
- mov registered_flag,0
- mov ax,-1 ;Return error
- end_installclock:
- ret
- installclock ENDP
-
- END
-